home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / makebin.com / MAKEBIN.DOC < prev    next >
Encoding:
Text File  |  1989-04-16  |  21.9 KB  |  467 lines

  1.                           MAKEBIN V1.0
  2.                           16 April 1989
  3.                          by Michael Day
  4.  
  5.      At  first  glance  it would seem to be  a  rather  pointless 
  6. effort  to  create a program that converts an EXE file to  a  BIN 
  7. file format. After all, the DOS utility EXE2BIN already  provides 
  8. that capability. Closer inspection will show however that the DOS 
  9. utility  EXE2BIN does not convert an EXE style program file to  a 
  10. BIN file, but rather it converts a transitional EXE file into the 
  11. BIN format that it is intended to be in. 
  12.  
  13.      If you wish to convert a normal EXE program file into a  BIN 
  14. file,  the usual response you will get is that it is  impossible. 
  15. As MAKEBIN shows, that's not entirely true. MAKEBIN can convert a 
  16. normal EXE program file into a BIN file. There are however a  few 
  17. limitations that are placed on the conversion.  
  18.  
  19.      The  primary limitation is that the size of the EXE  program 
  20. must  be  less  than  64K. This is not  a  direct  limitation  of 
  21. MAKEBIN,  but rather one that most loaders place on the BIN  file 
  22. size  because they don't know how to load a binary  image  larger 
  23. than 64K. 
  24.  
  25.      Another  limitation is that you cannot allocate,  change  or 
  26. de-allocate  DOS  memory within the BIN program.  There  are  two 
  27. reasons  behind this, one is because many programs that  allocate 
  28. memory  rely  on DOS to de-allocate the memory.  When  a  MAKEBIN 
  29. program is exited, it does not return through DOS, so the  memory 
  30. is not de-allocated, which would leave the DOS memory fragmented. 
  31. The other reason is that most loaders pre-allocate memory for the 
  32. BIN file, and do not take kindly to having memory yanked out from 
  33. under  them.  It is usually assumed by the loader  that  the  BIN 
  34. program will only use the program space initially given it by the 
  35. loader.
  36.  
  37.      The amount of memory needed for a program cannot be  readily  
  38. determined  for a standard BIN file because there is no  specific 
  39. field in the file that indicates how much memory it will require. 
  40. There  are usually two mechanisms used to handle this. One is  to 
  41. demand that the programmer specify the space that the program  is 
  42. to  be loaded into. Another common method found in most  database 
  43. programs  is  to  simply look at the size of  the  BIN  file  and 
  44. allocate  that much memory for the program. This works  for  most 
  45. binary image files, but EXE files allocate additional memory  for 
  46. themselves  beyond the actual program size when they are  loaded. 
  47.  
  48.    Since MAKEBIN was targeted for use with database programs, the 
  49. memory allocation problem was solved by re-sizing the EXE program 
  50. while  it is being converted to a BIN file. The size of  the  BIN 
  51. file is made to be equal to (actually slightly greater than)  the 
  52. amount  of memory the program needs. This places a limitation  on 
  53. the  total  memory usage of the EXE program to be less  than  64K 
  54. since that is the maximum file size that can be loaded.
  55.  
  56. Why use MAKEBIN?
  57.  
  58.      One  reason  is to be able to create a BIN  program  from  a 
  59. program  that  cannot normally create one such  as  Turbo  Pascal 
  60. V5.0. If you are used to programming in Turbo Pascal, but need to 
  61. create a BIN file (such as for use with Dbase III), MAKEBIN might 
  62. be the answer for you. 
  63.  
  64.  
  65. Why convert a perfectly good EXE file to a BIN file?
  66.  
  67.      Since  Dbase III normally allows you to run an  EXE  program 
  68. with  its  RUN  command, at first blush it would  seem  to  be  a 
  69. pointless  effort to go to all that extra effort to  convert  the 
  70. program  to  a  BIN  file just to be able  to  run  it  with  the 
  71. LOAD/CALL commands. There is a reason for the madness though.
  72.  
  73.      A  problem with the RUN command is that the program must  be 
  74. loaded from disk each time. This means that you must wait for the 
  75. program to be loaded each time you call it. For simple activities 
  76. this  may be an unacceptable delay. This is particularly true  if 
  77. the program must be closely tied to input or output activities. 
  78.  
  79.      When a program is loaded with the LOAD command, it stays  in 
  80. memory  ready for immediate use with the CALL command.  The  only 
  81. time you have to wait for the load from disk is when you use  the 
  82. LOAD command to initially load the program into memory.
  83.  
  84.  
  85. Creating programs for use with MAKEBIN
  86.  
  87.      MAKEBIN  was  targeted for use with Turbo  Pascal  V5.0  and 
  88. Database  programs like Dbase III. As such, I will be  discussing 
  89. issues  that  are  specific  to Turbo  Pascal  and  the  database 
  90. programs. However, there is no inherent limitation to prevent you 
  91. from using any EXE based program with MAKEBIN as long as it meets 
  92. the limitations presented. 
  93.  
  94.      While the issues I will cover are specific to Turbo  Pascal, 
  95. they  are applicable to other compiler/assemblers as well.  There 
  96. may be other issues that I have not anticipated or that might  be 
  97. applicable to another compiler that I haven't discussed. 
  98.  
  99.      The limitations and requirements that I discuss here  should 
  100. not  be  construed  to be the only ones involved.  It  should  be 
  101. realized that MAKEBIN is operating the EXE program in a condition 
  102. that  is  abnormal to its standard operating  environment.  As  a 
  103. result,  there may be any number of issues that will  affect  the 
  104. operation of the program that would not be a problem under normal 
  105. conditions.
  106.  
  107.  
  108. Standard EXE2BIN:
  109.  
  110.      By  far,  the easiest application of MAKEBIN  is  to  simply 
  111. convert  an  existing operational EXE program to a BIN  file.  No 
  112. other activity needs to be performed other than using MAKEBIN  to 
  113. convert the file and using the LOAD/CALL commands in the database 
  114. program to run it rather than using the RUN command.
  115.  
  116. Re-entrancy:
  117.  
  118.      There are limitations to converting a standard EXE file to a 
  119. BIN  file. The primary problem is when the program is  re-entered 
  120. after  the first call. Since the program remains in  memory,  any 
  121. typed  constant variables will be in the state they were in  when 
  122. the  program was exited from the last CALL. This could also be  a 
  123. problem if the program uses self-modifying code. The point  being 
  124. if the program expects things to be in a specific condition as  a 
  125. result  of  the initial load when it is run, you  may  experience 
  126. problems  since on the second CALL they may no longer be in  that 
  127. condition. 
  128.  
  129.      While Turbo Pascal itself does not have specific limitations 
  130. of  re-starting  a program that resides in  memory,  the  program 
  131. written may quite possibly have typed constants or self modifying 
  132. code in it that fall under this category of being a problem.
  133.  
  134.      On  the other hand, you can use this side effect to  control 
  135. successive  CALLs  to  the  program. Since  the  program  is  not 
  136. reloaded the typed constant will not be changed when the  program 
  137. is re-entered.
  138.  
  139.  
  140. Memory allocation:
  141.  
  142.      Since  a  BIN file will generally be  loaded  under  another 
  143. program,  MAKEBIN  will  allocate the minimum  amount  of  memory 
  144. possible  for  the program. In a Turbo Pascal program this  is  a 
  145. combination  of the program size, the data size, the stack  size, 
  146. and the minimum heap size specified. These are controlled by  the 
  147. $M compiler directive. Since the BIN file must be limited to less 
  148. than  64K in size, the combination of the various sizes must  not 
  149. exceed the 64K size limit.
  150.  
  151.      A BIN program created by MAKEBIN will not allow the  program 
  152. to allocate additional memory space beyond that initially defined 
  153. by the program.  Normally in a Turbo Pascal program this is not a 
  154. problem.  In  special cases, or in programs  generated  by  other 
  155. compilers it may be a problem.
  156.  
  157.      If  an  attempt is made to allocate more  memory  than  that 
  158. allocated  initially  to the program, an error will  be  returned 
  159. indicating  that  there  is  no  more  memory  available  to   be 
  160. allocated. 
  161.  
  162.      Another possible problem area is if the program attempts  to 
  163. change  it's own memory allocation size. Again, an error will  be 
  164. returned if this is attempted. Normally this is not a problem  in 
  165. a  Turbo  Pascal  program, though it may  occur  if  the  program 
  166. attempts to EXEC to DOS as it tries to free excess memory for use 
  167. by  the  shelled program. Since you cannot change  the  allocated 
  168. memory, this will result in an error condition being returned.
  169.  
  170.  
  171. Inter-Process Communications:
  172.  
  173.      Normally,  a  BIN  program communicates  with  it's  calling 
  174. program  via  register  variables.  MAKEBIN  provides  for   this 
  175. communications  with  an  interface  record  that  contains   the 
  176. register  values that existed upon entry to the BIN program,  and 
  177. which will be passed back to the calling program on exit from the 
  178. BIN program. Normally these register values should not be changed 
  179. unless explictly specified to do so by the calling program. 
  180.      
  181.      The  Inter-Process  Communications area can be  accessed  by 
  182. referencing  the pointer found at PspSeg-2. (A pointer  which  is 
  183. located two paragraphs, 32 bytes, below the BIN program's own PSP 
  184. segment.) The IPC pointer points to the record which contains the 
  185. register values.
  186.  
  187.      For database programs the registers DS:BX generally point to 
  188. a variable that is passed to the BIN program. Thus by creating  a 
  189. pointer  out  of  the values found in  registers  DS:BX  you  can 
  190. reference  the  database variable. Usually this  is  a  character 
  191. string,  but  it  can  be any  of  the  allowed  database  memory 
  192. variables.  The  demo programs provided show how  to  access  the 
  193. database string variable.
  194.  
  195. Redirect of BIN entry:
  196.  
  197.      The  BIN program must be entered normally the first time  so 
  198. that  it can be loaded and initialized. Once initialized  though, 
  199. you do not have to go through the entire initialization  sequence 
  200. again. Doing so can slow down the performance of the BIN  program 
  201. slightly  since  it has to go through the  entire  initialization 
  202. sequence each time it is called. 
  203.  
  204.      Redirecting  the entry point allows the BIN program  to  act 
  205. similar  to a TSR. In fact, much of the issues  and  requirements 
  206. involved are the same as with a TSR. 
  207.  
  208.      To  change  the  entry point, simply  call  the  SetBinEntry 
  209. procedure  at some point in the program. I recommend that  it  be 
  210. placed near the end of the program. Like a TSR, you need to  keep 
  211. the  Turbo program active for the functions to work.  This  means 
  212. that you must exit the program with the "Keep" procedure. 
  213.  
  214.      Since  Turbo  Pascal  programs also take over  a  number  of 
  215. interrupt vectors while it is in operation, you must also restore 
  216. the old vectors before returning to the calling database program. 
  217. You  can  use  the "SwapVectors" procedure  to  perform  this.  I 
  218. recommend  that  you  place all three calls at  the  end  of  the 
  219. program so that they won't get lost. 
  220.  
  221. Example:
  222.  
  223. begin
  224.    DoProgram...
  225.  
  226.    SetBinEntry(MyProc);
  227.    SwapVectors;
  228.    Keep(0);
  229. end.
  230.  
  231.  
  232.      You  may  want  to continue to use the  Turbo  Pascal  Error 
  233. handler  when you re-enter the program. If this is the case,  you 
  234. must  use the SwapVectors procedure to restore the  Turbo  Pascal 
  235. vectors  at the beginning of the re-entry into the  BIN  program, 
  236. and again at the exit.
  237.  
  238. Example:
  239.  
  240. {$F+}
  241. procedure MyProc;
  242. begin
  243.    SwapVectors;
  244.    
  245.    Dosomething....
  246.  
  247.    SwapVectors;
  248. end.
  249.  
  250.      Additionally, if you are using other functions within  turbo 
  251. that  require the use of the original interrupt vectors, such  as 
  252. the  80x87  emulation routines, You *must*  use  the  SwapVectors 
  253. procedure  or  strange things will happen. If you are  in  doubt, 
  254. then use the SwapVectors procedure. 
  255.  
  256.      You  should  *never* call a re-entrancy  procedure  directly 
  257. from the main BIN program (the part that is run the first  time). 
  258. This  is particularly true if you are swapping the  vectors.  The 
  259. SwapVectors  is  a  toggle.  It swaps the  old  vectors  with  an 
  260. internal  table.  Thus  if  you  were  to  call  the  re-entrancy 
  261. procedure  you would be swapping the old vectors back  in  losing 
  262. the ones you really want.
  263.  
  264.      Also note that the re-entered procedure has been declared as 
  265. FAR.  You  must *always* declare the re-entry procedure  as  FAR. 
  266. This is one area where the BIN program differs from a TSR. With a 
  267. TSR  you would declare the re-entry procedure as an  "Interrupt;" 
  268. procedure.  
  269.  
  270.      ** DO NOT **  declare the re-entry procedure as an interrupt 
  271. procedure.  It  may  appear  to  work,  but  when  the  procedure 
  272. terminates the BIN program's stack will become corrupted.  
  273.  
  274.      The   stack  corruption  is  caused  because  an   Interrupt 
  275. procedure has one additional word on the stack that contains  the 
  276. flags  prior to calling the interrupt procedure.   Declaring  the 
  277. procedure as an interrupt will cause the procedure to try to  pop 
  278. the  additional word from the stack. Since the BIN  loader  calls 
  279. the  procedure as a normal FAR procedure it will not have  placed 
  280. the  additional  word  on the stack. This  causes  the  stack  to 
  281. continually shrink until it wraps around into code or data  space 
  282. disrupting the program.
  283.  
  284.  
  285. Demo programs:
  286.  
  287.      The  Demo programs provided show how to create Turbo  Pascal 
  288. programs  which  can  be converted to BIN files for  use  with  a 
  289. database program. 
  290.  
  291.      The  first one is called BinDemo1. It consists of the  files 
  292. BinDemo1.Bin, BinDemo1.Prg, and BinDemo1.Pas (BinDemo1.Pas is the 
  293. source  to BinDemo1.Bin). BinDemo1 is a simple example of  a  BIN 
  294. program that was created by Turbo Pascal to run under a  database 
  295. program.  It uses an internal counter to keep track of each  time 
  296. it is entered. The program can accept a string variable from  the 
  297. database  program,  and  return a modified  string  back  to  the 
  298. program.  To run BinDemo1, just load Dbase or one of the  clones, 
  299. and enter the command "DO BINDEMO1".
  300.  
  301.      As  an  alternative, you can use the  BinRun  program  which 
  302. simulates  a database environment to run a BIN file.  BinRun  has 
  303. the  added advantage that you can run it under Turbo Debugger  so 
  304. that you can use it to debug the BIN program. To run the  program 
  305. with  BinRun, just enter "BINRUN BINDEMO1" at the DOS prompt.  To 
  306. run it under the Turbo Debugger enter "TD BINRUN BINDEMO1". 
  307.  
  308. Note:  The Turbo Debugger does not know how to access the  source 
  309. and  map tables for the BIN program because they aren't  included 
  310. in the EXE of the BinRun program, therefore you will only be able 
  311. to see the BIN program code in the CPU mode. 
  312.  
  313.      The other demo program is called BinDemo2, and includes  the 
  314. files  BinDemo2.Prg, BinDemo2.Bin, and BinDemo2.PAS. BinDemo2  is 
  315. similar  to  BinDemo1, except that it shows how to  redirect  the 
  316. entry point into the BIN program from the DataBase program. 
  317.  
  318.  
  319. Programs and files on the disk:
  320.  
  321.      MAKEBIN.DOC   This documentation file
  322.  
  323.      MAKEBIN.ASM   ASM Source for MAKEBIN
  324.      MAKEBIN.PAS   Pascal Source for MAKEBIN
  325.      MAKEBIN.EXE   The program to make a BIN file
  326.  
  327.      IPCUNIT.PAS   Pascal Source for a BIN interface
  328.  
  329.      BINDEMO1.BIN  Demo1 BIN program file
  330.      BINDEMO1.PRG  Demo1 database PRG file
  331.      BINDEMO1.PAS  Demo1 Pascal Source
  332.  
  333.      BINDEMO2.BIN  Demo2 BIN program file
  334.      BINDEMO2.PRG  Demo2 database PRG file
  335.      BINDEMO2.PAS  Demo2 Pascal Source
  336.  
  337.      BINRUN.PAS    Pascal Source for BINRUN
  338.      BINRUN.EXE    The program to simulate a database environment
  339.  
  340.      MAKEHEX.PAS   Utility used to convert an assembler hex file
  341.      MAKEHEX.EXE   to a hex format acceptable for Turbo Pascal
  342.  
  343. Using MAKEBIN:
  344.  
  345.      To use MAKEBIN, just create your program using Turbo  Pascal 
  346. as  you normally would, compile it to an EXE file, then  run  the 
  347. MAKEBIN program to convert it to a BIN file. That's all there  is 
  348. to it. Couldn't be simpler right?
  349.  
  350.  
  351. How does it work?
  352.  
  353.      A  BIN file normally starts with a code offset of zero,  and 
  354. is  a  simple memory image of the code to be run.  This  is  very 
  355. similar to a COM file except that there is no PSP or other system 
  356. hooks  to worry about, just a simple memory image of the  program 
  357. segment. 
  358.  
  359.      An  EXE  file on the other hand is a  complex  program  file 
  360. which  requires  hooks  to the operating system  (the  PSP),  and 
  361. special  treatment to prepare the program contained in  the  file 
  362. before  it  is  run.  This requires that an  EXE  be  provided  a 
  363. "loader" so that it can be properly converted. 
  364.  
  365.      MakeBin builds a loader onto the front of the EXE program so 
  366. that  it can be "Loaded" the first time it is called. A  flag  is 
  367. then set indicating that it has been loaded so that that  portion 
  368. of  the  loader will be bypassed on successive calls to  the  BIN 
  369. program. 
  370.  
  371.      The Loader converts the special memory image of the EXE file 
  372. into the relocated memory image required to run the program. This 
  373. must  be done at load time since it is not known where in  memory 
  374. the program will reside until it has been loaded at run time.
  375.  
  376.      MakeBin  also attaches a dummy PSP to the beginning  of  the 
  377. program. This PSP is a copy of the database program's PSP. Unlike
  378. an  EXEC'd  program  which gets a "child" PSP all  its  own,  the 
  379. MakeBin  created PSP is a replicate of the database PSP.  It  has 
  380. direct  access  to  several of the database's  PSP  hooks.  These 
  381. include  the  database's  environment pointer,  and  it's  handle 
  382. table.
  383.  
  384.      The  reason  why  a  replicate PSP is  used  rather  than  a 
  385. separate  child  PSP is because normally a BIN program  does  not 
  386. have  it's own PSP, therefore it uses the database program's  PSP 
  387. if  it  needs access to one. EXE type programs  however  normally 
  388. expect  to  have  their  own PSP to work  with.  This  can  cause 
  389. conflicts as the EXE program may try to modify what it thinks  is 
  390. its own PSP. Such an action can disrupt the PSP for the database, 
  391. so a mechanism was need to isolate the PSP for the BIN file while 
  392. still  allowing  it to think that it had access to  the  database 
  393. PSP. Replicating the database PSP was the answer. 
  394.  
  395.      Replicating the PSP also allows one other aspect of the  PSP 
  396. to be handled. The memory size block must be set to what the  BIN 
  397. program  will  expect to see. By using the replicate PSP  we  can 
  398. change this without affecting the database PSP. It also lets  the 
  399. BIN  program  change  the  return  vectors  in  the  PSP  without 
  400. adversely affecting the database PSP.
  401.  
  402.      Normally a well behaved program will keep track of it's  PSP 
  403. segment  by  saving  the segment location feed to it  in  the  ES 
  404. segment register when the program is run. Some less well  behaved 
  405. programs though expect the PSP to be immediately in front of  the 
  406. program  itself.  This is normally true, but not  always  so.  By 
  407. creating  our  own  PSP, we can place it  immediately  below  the 
  408. program so that even an ill-behaved program won't get upset. 
  409.  
  410.      Another  area of concern, though much less so than the  PSP, 
  411. is  the MCB. Very few programs make use of the MCB, but some  do. 
  412. Once  again, a well behaved program would not present  a  problem 
  413. since it would use the DOS function to get the base MCB and  then 
  414. search through the chain for its own MCB. An ill-behaved  program 
  415. though  may expect to find its MCB immediately below the PSP.  As 
  416. such,  MAKEBIN creates a dummy MCB immediately below the  PSP  to 
  417. keep  the ill-behaved program happy. The dummy MCB is created  to 
  418. appear  to be the BIN program's MCB, and is the last MCB  in  the 
  419. chain. This is a dummy MCB however, and it does not really appear 
  420. in the MCB chain. It can only be found by an ill behaved  program 
  421. that assumes the MCB to be immediately below the PSP. 
  422.  
  423.      Since  the  BIN program often has to  communicate  with  the 
  424. database  program,  one additional paragraph has  been  allocated 
  425. just below the dummy MCB. The first location of this paragraph is 
  426. the  only one that is used. It contains a pointer to a  table  in 
  427. memory  of the register values that were saved upon entry to  the 
  428. BIN  program  from the database program. From Turbo  Pascal  this 
  429. table can be accessed by referring to "PspSeg-2".
  430.  
  431. Using the IPC unit:
  432.  
  433.      To make many of these programming issues easier for you, the 
  434. unit "IpcUnit" was created to provide the various parameters  and 
  435. functions needed. Simply include it in your Uses statement at the 
  436. beginning of your program. It does not require that it be in  any 
  437. special  order  with  respect  to other  units,  other  then  any 
  438. possible  dependency  that  the other units  might  have  on  the 
  439. IpcUnit.
  440.  
  441.      MAKEBIN.PAS  is  the source file to MAKEBIN.EXE.  It's  main 
  442. purpose is to append the custom loader onto the front of the  EXE 
  443. file (the large HEX table in the file) and to adjust the size  of 
  444. the  file  to  be the desired size for a BIN file  (equal  to  or 
  445. larger  than  the  total memory area used by  the  program).  The 
  446. MAKEBIN  program also assists in the filename creation by  adding 
  447. the  required  EXE  and BIN file extensions to the  names.  If  a 
  448. second  filename  parameter is not given, then the  BIN  file  is 
  449. assumed to have the same name as the EXE file.
  450.  
  451.      MAKEBIN.ASM is the assembler source to the hex table in  the 
  452. MAKEBIN.PAS  program. It is written for the Seattle Assembler.  I 
  453. use  the Seattle Assembler because it is fast and  generates  hex 
  454. files directly. Unfortunately, the hex file generated by the  the 
  455. assembler  is  not exactly in the form needed to  incorporate  it 
  456. directly into the Pascal program. Thus the existence of  MAKEHEX, 
  457. which  converts  the  Intel  format  hex  file  produced  by  the 
  458. assembler  into  the  form needed to insert  it  into  the  typed 
  459. constant array used in MAKEBIN.
  460.  
  461. MS-DOS is a registered trademark of MicroSoft Corp.
  462. Dbase is a registered tradmark of Aston-Tate.
  463. Seattle Assmebler is produced by Seattle Computer Products
  464. MakeBin belongs to me, Michael Day. So there! Nah!
  465.  
  466. <eof>
  467.